/* 
 * File:   util.h
 * Author: skyro
 *
 * Created on December 16, 2010, 11:08 PM
 */

#ifndef _UTIL_H
#define	_UTIL_H

#include <iostream>
#include "types.h"

#if ASSERTIONS_ENABLED

    // define some inline assembly that causes a break
    // into the debugger - this will be different on
    // differnt ISA.
    #define debugBreak() asm("int $3")

    // check the expression and fail if it's false
    #define ASSERT(expr)    \
        if(expr){} \
        else{ \
            reportAssertionFailure(#expr,   \
                __FILE__,   \
                __LINE__);  \
            debugBreak();   \
        }
#else
    #define ASSERT(expr)
#endif

inline void reportAssertionFailure(const char* msg, const char* file, int line)
{
    std::cerr<<"Assertion Failure: "<<msg<<" at "<<file<<", line "<<line<<"\n";
}

// singleton template type
template <class T>
class Singleton
{
public:
    static T& Instance()
    {
        if(!m_pInstance)
        {
            m_pInstance = new T;
        }
        ASSERT(m_pInstance != 0);
        return *m_pInstance;
    }
protected:
    Singleton(){};
    ~Singleton(){};
private:
    Singleton(Singleton const&);
    Singleton& operator=(Singleton const&);
    static T* m_pInstance;
};

template<class T>
T* Singleton<T>::m_pInstance = 0;


void reportAssertionFailure(const char* msg, const char* file, int line);

#endif	/* _UTIL_H */

